/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Advanced Text Box Class
 *      Extends the original text box class to allow for numeric-
 * only entries, and provides the Deactivated event.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Extends the original text box class to allow for numeric-
    /// only entries, and provides the Deactivated event.
    /// </summary>
    [Browsable(true), ToolboxItem(true), DesignerCategory("TextBox"),
    ToolboxBitmap(typeof(EmbeddedResourceFinder), "Adaptive.Foundation.Windows.Forms.AdvancedTextBox.bmp")]
    public partial class AdvancedTextBox : TextBox
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when the control is de-activated.  This is different 
        /// from <see cref="Control.LostFocus"/>
        /// </summary>
        public event EventHandler Deactivated;
        /// <summary>
        /// Occurs when the <see cref="CatchCrLf"/> property is <b>true</b> and a user 
        /// presses the Enter/Return key.
        /// </summary>
        public event EventHandler ReturnPressed;
        /// <summary>
        /// Occurs when the control is in masked edit mode and the user enters invalid
        /// text.
        /// </summary>
        public event EventHandler TextInvalid;
        /// <summary>
        /// Occurs when the user presses a key considered to be a punctuation character.
        /// </summary>
        public event KeyPressEventHandler PunctuationCharPressed;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        /// <summary>
        /// API Control deactivation message.
        /// </summary>
        private const int WM_ACTIVATEAPP = 0x1C;

        private const string FORMAT_COMMAS = "###,###,###,###,###,###,##0";
        private const string FORMAT_NOCOMMAS = "#####################0";

        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Flag to turn on/off the numeric entry restrictions.
        /// </summary>
        private bool _numeric;
        /// <summary>
        /// Flag to allow/disallow numbers with decimals.
        /// </summary>
        private bool _allowFloat = true;
        /// <summary>
        /// Flag to allow/disallow negative numbers.
        /// </summary>
        private bool _allowNegative;
        /// <summary>
        /// Flag to select all text when the control Getsfocus.
        /// </summary>
        private bool _selectAllonFocus = true;
        /// <summary>
        /// Flag to allow/disallow use of commas in formatted string.
        /// </summary>
        private bool _useCommas = true;
        /// <summary>
        /// Flag to catch enter key.
        /// </summary>
        private bool _catchCrLf;
        /// <summary>
        /// Sets the number of decimal places in the format.  
        /// </summary>
        private int _decimals = 4;
        /// <summary>
        /// Mask edit regular expression.
        /// </summary>
        private Regex _expression;
        /// <summary>
        /// Mask edit key-press regular expression.
        /// </summary>
        private Regex _keyPressExpression;
        /// <summary>
        /// Masked edit mode.
        /// </summary>
        private MaskedEditMode _mode = MaskedEditMode.None;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public AdvancedTextBox()
            : base()
        {
            InitializeComponent();
        }
        /// <summary>
        /// Another constructor for the class, this method allows the developer to specify
        /// the mask mode and expressions to be used.
        /// </summary>
        /// <param name="mode">The mask mode (i.e. per character, on leave, or both) to be employ</param>
        /// <param name="leaveExpression">The expression used to evalute input on leave</param>
        /// <param name="keystrokeExpression">The expression used to evaluate input as characters are typed</param>
        public AdvancedTextBox(MaskedEditMode mode, string leaveExpression,
            string keystrokeExpression)
            : base()
        {
            InitializeComponent();

            //Set properties.
            _numeric = false;
            _mode = mode;

            //initialize appropriate expressions
            switch (_mode)
            {
                case MaskedEditMode.KeyPress:
                    _keyPressExpression = new Regex(keystrokeExpression);
                    break;
                case MaskedEditMode.Leave:
                    _expression = new Regex(leaveExpression);
                    break;

                case MaskedEditMode.Both:
                    _keyPressExpression = new Regex(keystrokeExpression);
                    _expression = new Regex(leaveExpression);
                    break;
            }
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }

            _keyPressExpression = null;
            _expression = null;
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*------------------------------------------------------------------------
		 * Public Properties
		 *----------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
		/// Gets or sets a value indicating whether the text box is a numeric-only 
		/// text box.
		/// </summary>
		/// <value>
		/// <b>true</b> if the text box only allows numbers; otherwise, <b>false</b>.
		/// </value>
		/// <remarks>
		/// Setting this property disables the masked-edit functionality.  If the value
		/// is <b>true</b>, then only numbers may be entered.  Negative signs and decimals
		/// points are optional depending on the settings for [see cref="AllowFloatingPointNumbers"/>,
		/// and <see cref="AllowNegativeNumbers"/>.  Formatting options for this mode only 
		/// are set in the [see cref="DecimalPlaces"/> and the [see cref="UseCommas"/> 
		/// properties.  These properties only affect the text box if the <b>Numeric</b> 
		/// property is <b>true</b>.
		/// </remarks>
		[Browsable(true), Category("Behavior"), DefaultValue(false), 
		Description("Gets or sets the flag to restrict keystroke entry to numeric values.")]
		public bool Numeric
		{
			get{return _numeric;}
			set
			{
				if (value)
					Mask = string.Empty;
				_numeric = value;
			}
		}
		/// <summary>
		/// Gets or sets value indicating whether the text box allows floating 
		/// point numbers to be entered in numeric mode.
		/// </summary>
		/// <value>
		/// <b>true</b> if floating point numbers are allowed; otherwise <b>false</b>.
		/// </value>
		/// <remarks>
		/// This property only takes effect if the <see cref="Numeric"/> property is 
		/// set to <b>true</b>.
		/// </remarks>
		[Browsable(true), Category("Format"), DefaultValue(true), 
		Description("Allow or disallow entry of floating point numbers")]
		public bool AllowFloatingPointNumbers
		{
			get{return _allowFloat;}
			set
			{
				_allowFloat = value;
				if (_numeric)
					base.Text = FormatValue(Value);
			}
		}
		/// <summary>
		/// Gets or sets value indicating whether the text box allows negative  
		/// numbers to be entered in numeric mode.
		/// </summary>
		/// <value>
		/// <b>true</b> if negative numbers are allowed; otherwise <b>false</b>.
		/// </value>
		/// <remarks>
		/// This property only takes effect if the <see cref="Numeric"/> property is 
		/// set to <b>true</b>.
		/// </remarks>
		[Browsable(true), Category("Format"), DefaultValue(false), 
		Description("Allow or disallow entry of negative numbers")]
		public bool AllowNegativeNumbers
		{
			get{return _allowNegative;}
			set
			{_allowNegative = value;}
		}
		/// <summary>
		/// Gets or sets a value indicating whether the text box will select all its
		/// contents when the control is entered.
		/// </summary>
		/// <value>
		/// <b>true</b> if the contents are to be selected when the control is entered;
		/// otherwise <b>false</b>.
		/// </value>
		[Browsable(true), Category("Selection"), DefaultValue(true), 
		Description("Flag to select all text when control gets focus")]
		public bool SelectAllOnEnter
		{
			get{return _selectAllonFocus;}
			set
			{_selectAllonFocus = value;}
		}
		/// <summary>
		/// Gets or sets the number of decimal places to use in numeric mode only.
		/// </summary>
		/// <value>
		/// The maximum number of decimal places allowed.
		/// </value>
		/// <remarks>
		/// This property only takes effect if the <see cref="Numeric"/> property is 
		/// set to <b>true</b>.
		/// </remarks>
		[Browsable(true), Category("Format"), DefaultValue(4), 
		Description("Gets or sets the number of decimal places to use in the numeric formatting.")]
		public int DecimalPlaces
		{
			get{return _decimals;}
			set{_decimals = value;}
		}
		/// <summary>
		/// Gets or sets a value indicating whether numeric text will include comma
		/// separators.
		/// </summary>
		/// <value>
		/// <b>true</b> if commas are used; otherwise, <b>false</b>.
		/// </value>
		/// <remarks>
		/// This property only takes effect if the <see cref="Numeric"/> property is 
		/// set to <b>true</b>.  In this case, the comma formatting is not applied
		/// during item entry, but the formatting is applied on the control's 
		/// <see cref="System.Windows.Forms.Control.Leave"/> event. 
		/// </remarks>
		/// [example>
		/// Given that the <see cref="Numeric"/> property is <b>true</b>, and the
		/// text value is "12345678":
		/// 
		/// If the <b>UseCommas</b> property is <b>true</b>, the text will appear
		/// in the control as: "12,345,678";
		/// 
		/// If the <b>UseCommas</b> property is <b>false</b>, the text will appear
		/// in the control as: "12345678";
		/// [/example>
		[Browsable(true), Category("Format"), DefaultValue(true), 
		Description("Allow or disallow use of commas in text format.")]
		public bool UseCommas
		{
			get{return _useCommas;}
			set{_useCommas = value;}
		}
		/// <summary>
		/// Gets or sets the value of the text as a double nueric value, if 
		/// in numeric mode.
		/// </summary>
		/// <value>
		/// The numeric value of the current text if in numeric mode, otherwise 
		/// zero (0).
		/// </value>
		/// <remarks>
		/// If the control is not in numeric mode, setting this property has no
		/// effect and the property always returns zero (0).
		/// </remarks>
		[Browsable(true), Category("Data"), DefaultValue(0), 
		Description("The numeric value of the control's text.")]
		public double Value
		{
			get
			{
				if (_numeric)
					return m_GetValue();
				else
					return 0;
			}
			set
			{
				if (_numeric)
					base.Text = FormatValue(value);
			}
		}
		/// <summary>
		/// Getsor sets the text content of the text box.
		/// </summary>
		/// <value>
		/// The text content of the text box. The default is a blank string ("").
		/// </value>
		/// <remarks>
		/// If in numeric mode when setting this property, the value will be formatted
		/// as a number and then stored in the property.
		/// </remarks>
		[Browsable(true), Category("Data"), DefaultValue(""), 
		Description("The current text value.")]
		public override string Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				base.Text = value;
				if (_numeric)
					base.Text = FormatValue(Value);
			}
		}
		/// <summary>
		/// Gets a value indicating whether the control will raise an event when the return key is pressed.
		/// </summary>
		/// <value>
		/// <b>true</b> if the <see cref="ReturnPressed"/> event is to be raised when the
		/// enter/return key is pressed; otherwise <b>false</b>.
		/// </value>
		[Browsable(true), Category("Behavior"), DefaultValue(false), 
		Description("Indicates whether the control will raise an event when the return key is pressed.")]
		public bool CatchCrLf
		{
			get{ return _catchCrLf;}
			set{_catchCrLf = value;}
		}
		/// <summary>
		/// By applying the Editor attribute we can specify a class dervied from
		/// System.Drawing.Design.UITypeEditor; this class will define the user 
		/// interface presented when the property is modified from Visual Studio .NET.
		/// 
		/// The Description attribute is used to provide context help in the 
		/// properties windows of Visual Studio .NET.
		/// 
		/// The DefaultValue attribute can be used to specify a default value for the 
		/// property (in this case, we can use it to specify the default regular 
		/// expression to be used).
		/// 
		/// The Expression property itself is used to store the regular expression 
		/// that will be used to evaluate/mask the input into this control after the control
		/// is left.
		/// 
		/// Setting this property to a blank string allows the text box to operate normally
		/// or in numeric mode.  Setting the property to any other value disables numeric mode.
		/// </summary>
		[Editor(typeof(System.Web.UI.Design.WebControls.RegexTypeEditor), 
			 typeof(System.Drawing.Design.UITypeEditor)), 
		Description("Use this property to select or specify the regular expression to validate the control."), 
		DefaultValue(" ")]
		public string Mask
		{
			get
			{

				if (_expression == null)
					return string.Empty;
				else if (_expression.ToString().Length > 0)
					return _expression.ToString();
				else
					return string.Empty;
			}
			set
			{
				if (value.Length == 0)
					_expression = null;
				else
				{
					_numeric = false;
					_expression = new Regex(value);
				}
			}
		}
		/// <summary>
		/// Sets the mask for each keystroke.
		/// </summary>
		/// <remarks>
		/// Settings this property to anything other than a blank string disables numeric
		/// mode.
		/// </remarks>
		public string KeyPressMask
		{
			get
			{
				if ((_keyPressExpression == null) || (_keyPressExpression.ToString().Length == 0))
					return string.Empty;
				else
					return _keyPressExpression.ToString();
			}
			set
			{
				if (value.Length == 0)
					_keyPressExpression = null;
				else
					_keyPressExpression = new Regex(value);
			}
		}
		/// <summary>
		/// Determines the when the mask filter is applied, if in masked edit mode.
		/// </summary>
		/// <value>
		/// The current masked filter mode in use.
		/// </value>
		public MaskedEditMode MaskedEditMode
		{
			get{return _mode;}
			set
			{
				if (_numeric)
					_mode = MaskedEditMode.None;
				else
					_mode = value;
			}
		}
		#endregion

		/*------------------------------------------------------------------------
		 * Protected Methods / Functions
		 *----------------------------------------------------------------------*/
		#region Protected Methods / Functions
		/// <summary>
		/// Processes incoming Windows messages.
		/// </summary>
		/// <param name="m">The event message to be processed.</param>
		protected override void WndProc(ref Message m)
		{
			//Intercepts Windows messages.

			//Allow the base class to process all Windows messages first.
			base.WndProc(ref m);

			//If the message is the activate command with the deactivate parameter,
			//raise the Deactivated event.
			if (m.Msg == WM_ACTIVATEAPP)
			{
				if (m.WParam.ToInt32() == 0)
					OnDeactivated(new EventArgs());
			}
		}
		/// <summary>
		/// Raises the <see cref="Deactivated"/> event.
		/// </summary>
		protected virtual void OnDeactivated(EventArgs e)
		{
			//Provided to raise the Deactivated event.
			if (Deactivated != null)
				Deactivated(this, e);
		}
		/// <summary>
		/// Processes key strokes. 
		/// </summary>
		/// <param name="e">A <see cref="KeyPressEventArgs"/> class containing the
		/// keystroke that caused the event.</param>
		/// <remarks>
		/// In normal mode, this routine does nothing but raise the <see cref="Control.KeyPress"/>
		/// event.  In numeric mode, this routine is designed to parse out all non-numeric characters from being entered into the control.
		/// </remarks>
		protected override void OnKeyPress(KeyPressEventArgs e)
		{
			//Main functionality of this control.  This routine is designed to parse
			//out all non-numeric characters from being entered into the control.
			int cursorPos = 0;

			//Catch a return being pressed.
			if ((_catchCrLf) && (e.KeyChar == 13))
			{
				e.Handled = true;
				OnReturnPressed(new EventArgs());
			}
			else
			{

				if (_numeric)
				{
					//Test to see if the ascii character is within specified values.
					//Test for numbers (0 - 9)
					if (!Char.IsNumber(e.KeyChar))
					{
						//Test for backspace and tab characters...
						if (!Char.IsControl(e.KeyChar))
						{
							//If floating point numbers are allowed, then test for 
							//the "period".
							if ((_allowFloat) && (Char.IsPunctuation(e.KeyChar)))
							{
								if (e.KeyChar == '.')
								{
									//Allow if a "dot" is not already in the number.
									if (Text.IndexOf(".") != -1)
										e.Handled = true;
								}
								else
								{
									e.Handled = true;
									//If negative numbers are allowed, then check the current
									//text value.  If a negative sign is not present, add a negative
									//sign to the start of the text. (i.e. "123" becomes "-123").
									//Otherwise, remove the negative sign.
									if ((e.KeyChar == '-') && (_allowNegative))
									{
										//Store the current cursor position
										cursorPos = SelectionStart;
										if (Text.IndexOf("-") == -1)
										{
											base.Text = "-" + Text;
											cursorPos++;
										}
										else
										{
											base.Text = Text.Substring(1, Text.Length - 1);
											cursorPos--;
										}

										//Restore the cursor to the previous location.
										if ((cursorPos >= 0) && (cursorPos <= base.Text.Length - 1))
											SelectionStart = cursorPos;
		
									}
								}
							}
							else
							{
		
								//If negative numbers are allowed, then check the current
								//text value.  If a negative sign is not present, add a negative
								//sign to the start of the text. (i.e. "123" becomes "-123").
								//Otherwise, remove the negative sign.
								if ((e.KeyChar == '-') && (_allowNegative))
								{
									//Store the current cursor position
									cursorPos = SelectionStart;
									if (Text.IndexOf("-") == -1)
									{
										base.Text = "-" + Text;
										cursorPos++;
									}
									else
									{
										base.Text = Text.Substring(1, Text.Length - 1);
										cursorPos--;
									}
			

									//Restore the cursor to the previous location.
									if (( cursorPos >= 0) && (cursorPos <= base.Text.Length - 1))
										SelectionStart = cursorPos;
		
								}
								OnPunctuationCharPressed(e);
								e.Handled = true;
							}
						}
						else
							base.OnKeyPress(e);
					}
					else
					{
						////Evaluate each keystroke?  (i.e. if mode is "Leave" then exit)
						if ((_mode == MaskedEditMode.Leave) || (_mode == MaskedEditMode.None)) 
						{
							//allows further processing (e.g. writing the character) by base class
							e.Handled = false;
							//send all event args to base class, including the above property that
							//indicates to the base class to process the input
							base.OnKeyPress(e);
						}
						else
						{
					
							//determine if there is a match
							Match patternMatch = null;
							patternMatch = _keyPressExpression.Match(base.Text + e.KeyChar);

							//if so, then do nothing and call allow input
							if ((patternMatch.Success) && (patternMatch.Length == base.Text.Length + 1))
								e.Handled = false;  //allows further processing of input
								//otherwise, prevent input
							else
							{
								e.Handled = true; //prevents further processing of input

								//send all event args to base class, including the above property that
								//indicates to the base class to process the input
								base.OnKeyPress(e);
							}
						}
					}
				}
			}
		}
		/// <summary>
		/// Optionally select all text when the control gets focus, and raises the
		/// <see cref="Control.Enter"/> event.
		/// </summary>
		protected override void OnEnter(EventArgs e)
		{
			//Optionally select all text when the control gets focus.
			if (_selectAllonFocus)
			{
				SelectionStart = 0;
				SelectionLength = Text.Length;
			}
		
			base.OnEnter(e);
		}
		/// <summary>
		/// Forces the current text to an appropriate value/format once the control loses focus,
		/// and raises the <see cref="Control.Leave"/> event.
		/// </summary>
		protected override void OnLeave(EventArgs e)
		{
			//Force the current text to an appropriate value/format once
			//the control loses focus.
			double dblValue = 0;
			string last = string.Empty;

			if (_numeric)
			{
				//Parse the current text into a numeric value.
				dblValue = Value;
				Value = dblValue;

				//Format the text display.
				Text = FormatValue(dblValue);
				base.OnLeave(e);
			}
			else
			{
		
				//evalute?  (i.e. if mode is KeyPress then exit)
				if ((_mode != MaskedEditMode.KeyPress) && (_mode != MaskedEditMode.None))
				{
					Match patternMatch = null;

					//determine if there is a match
					patternMatch = _expression.Match(base.Text);

					//if there is a match containing the whole input string
					if ((patternMatch.Success) && (patternMatch.Length == base.Text.Length))
					{
						//store valid value
						last = base.Text;

						//call TextBox control//s OnLeave
						base.OnLeave(e);
					}
					else
					{
						if (TextInvalid != null)
							TextInvalid(this, e);
					}
				}
			}
		}
		/// <summary>
		/// Raises the <see cref="ReturnPressed"/> event.
		/// </summary>
		protected virtual void OnReturnPressed(EventArgs e)
		{
			if (ReturnPressed != null)
				ReturnPressed(this, e);
		}
		/// <summary>
		/// Raises the <see cref="PunctuationCharPressed"/> event.
		/// </summary>
		/// <param name="e"></param>
		protected virtual void OnPunctuationCharPressed(KeyPressEventArgs e)
		{
			if (PunctuationCharPressed != null)
				PunctuationCharPressed(this, e);
		}
		#endregion

		/*------------------------------------------------------------------------
		 * Public Methods / Functions
		 *----------------------------------------------------------------------*/
		#region Public Methods / Functions
		/// <summary>
		/// Gets the current text value as an integer.
		/// </summary>
		/// <returns>The current text value converted to an integer.</returns>
		public int ToInteger() 
		{
			// Return the current value as an Integer.
			int returnValue = 0;
			try 
			{
				returnValue = Convert.ToInt32(Value);
			}
			catch 
			{
				returnValue = 0;
			}
			return returnValue;
		}
		/// <summary>
		/// Gets the current text value as a single precision floating point number.
		/// </summary>
		/// <returns>The current text value as a single precision floating point number.</returns>
		public float ToSingle() 
		{
			// Return the current value as a single.
			float returnValue = 0;

			try 
			{
				returnValue = Convert.ToSingle(Value);
			}
			catch 
			{
				returnValue = 0;
			}
			return returnValue;
		}
		#endregion

		/*------------------------------------------------------------------------
		 * Private Methods / Functions
		 *----------------------------------------------------------------------*/
		#region Private Methods / Functions

		private double m_GetValue() 
		{
			double returnValue = 0;				//Return value.
			bool fail = false;					//Conversion failure flag.
			string text = string.Empty;			//Text to convert.

			// Trim the text.
			if (base.Text.Length == 0)
				base.Text = "0";

			text = base.Text.ToLower().Trim();

			// Change accounting negative style to standard. (Replace () with -)
			if ((text.Length >= 2)) 
			{
				if ((text.Substring(0, 1) =="(") &&
					(text.Substring((text.Length - 1), 1) == ")"))
				{
					text = ("-" + text);
				}
			}
			// Replace all remaining odd, invalid characters in the current Text property.
			text = text.Replace("$", string.Empty).Replace(
						"(", string.Empty).Replace(")", string.Empty).Replace(
						"!", string.Empty).Replace("%", string.Empty).Replace(
						"*", string.Empty).Replace("&", string.Empty);

			// Replace imaginary value strings.
			text = text.Replace("NaN", "0");
			// Convert the string to a double.
			if (text.Length == 0)
			{
				returnValue = 0;
			}
			else 
			{
				// Try the basic conversion first.
				try 
				{
					returnValue = Convert.ToDouble(text);
				}
				catch 
				{
					fail = true;
				}
				if (fail) 
				{
					// If the basic conversion failed, try the Decimal object.
					try 
					{
						returnValue = (double)(Convert.ToDecimal(text));
					}
					catch 
					{
						returnValue = 0;
					}
				}
			}
			// Return the final value.
			return returnValue;
		}
    
		private string FormatValue(double originalValue) 
		{
			int count = 0;							//Iteration counter.
			string returnValue = string.Empty;		//Return value.
			StringBuilder builder = null;			//String concatenator.

			builder = new StringBuilder();

			if (base.Text != "-")
			{
				//Set format string according to property settings.
				if (_useCommas)
                    builder.Append(FORMAT_COMMAS);
				else
                    builder.Append(FORMAT_NOCOMMAS);
                
				if ((_allowFloat) && (_decimals > 0))
				{
					builder.Append(".");
					for(count = 0; count < _decimals; count++)
						builder.Append("0");
				}
			}

            //Now format the string.
            returnValue = originalValue.ToString(builder.ToString());
			builder = null;
            return returnValue;
		}
		#endregion
	}
}
